﻿using MyGIS;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;
using System.IO;

namespace MyGIS
{


    public class GISVertex   //节点类

    {
        public double x;
        public double y;
        public GISVertex(double _x, double _y)
        {
            x = _x;
            y = _y;
        }//外部传参，向x与y赋值
        public double Distance(GISVertex anothervertex)
        {
            return Math.Sqrt((x - anothervertex.x) *
                (x - anothervertex.x) + (y - anothervertex.y) * (y - anothervertex.y));
        }//计算两点间距离


        public void CopyFrom(GISVertex v)//使用输入点替换当前点
        {
            x = v.x;
            y = v.y;
        }
    }


    public class GISPoint : GISSpatial  //点实体
    {

        public GISPoint(GISVertex onevertex)
        {
            centroid = onevertex;
            extent = new GISExtent(onevertex, onevertex);
        }//实例化点实体
        public override void draw(Graphics graphics,GISView view)
        {
            Point screenpoint = view.ToScreenPoint(centroid);
            graphics.FillEllipse(new SolidBrush(Color.Red),
                new Rectangle(screenpoint.X - 3, screenpoint.Y - 3, 6, 6));
        }//在屏幕上画出点实体
        public double Distance(GISVertex anothervertex)
        {
            return centroid.Distance(anothervertex);
        }//计算两点间距离
    }
    public class GISLine : GISSpatial
    {
        List<GISVertex> AllVertexs;
        public override void draw(Graphics graphics,GISView view)
        {

        }
    }
    public class GISPolygon : GISSpatial
    {
        List<GISVertex> AllVertexs;
        public override void draw(Graphics graphics,GISView view)
        {

        }
    }


    public class GISFeature   //空间要素特征类
    {
        public GISSpatial spatialpart;  //对象的空间信息
        public GISAttribute attributepart;  //对象的属性信息
        public GISFeature(GISSpatial spatial, GISAttribute attribute)
        {
            spatialpart = spatial;
            attributepart = attribute;
        }
        public void draw(Graphics graphics,GISView view, bool DrawAttributeOrNot, int index)
        {
            spatialpart.draw(graphics,view);
            if (DrawAttributeOrNot)
            {
                attributepart.draw(graphics,view, spatialpart.centroid, index);
            }
        }
        public object getAttribute(int index)
        {
            return attributepart.GetValue(index);
        }
    }


    public class GISAttribute
    {
        public ArrayList values = new ArrayList();
        public void AddValue(object o)  //添加属性值
        {
            values.Add(o);
        }
        public object GetValue(int index)  //获取属性值
        {
            return values[index];
        }
        public void draw(Graphics graphics, GISView view, GISVertex location,int index)
        {
            Point screenpoint = view.ToScreenPoint(location);
            graphics.DrawString(values[index].ToString(),
                new Font("宋体", 20),
                new SolidBrush(Color.Green), 
                new PointF(screenpoint.X,screenpoint.Y));
        }//画出属性信息
    }


    public abstract class GISSpatial  //抽象空间要素类
    {
        public GISVertex centroid;//空间实体的中心点
        public GISExtent extent;//空间范围：最小外接矩形
        public abstract void draw(Graphics graphics,GISView view);
    }


    public class GISExtent   //空间对象面积类
    {
        public GISVertex bottomleft;
        public GISVertex upright;
        double ZoomingFactor = 2;//缩放系数，放大或缩小时会缩放为2倍或二分之一
        double MovingFactor = 0.25;//移动系数，即移动一次会有四分之一的屏幕范围移除屏幕

        /// <summary>
        /// 显示范围（左下角点，右上角点）
        /// </summary>
        /// <param name="_bottomleft"></param>
        /// <param name="_upright"></param>
        public GISExtent(GISVertex _bottomleft, GISVertex _upright)
        {
            bottomleft = _bottomleft;
            upright = _upright;
        }
        public double getMinX()
        {
            return bottomleft.x;
        }
        public double getMaxX()
        {
            return upright.x;
        }
        public double getMinY()
        {
            return bottomleft.y;
        }
        public double getMaxY()
        {
            return upright.y;
        }
        public double getWidth()  //计算地图横坐标长度
        {
            return upright.x - bottomleft.x;
        }
        public double getHeight()  //计算地图纵坐标长度
        {
            return upright.y - bottomleft.y;
        }
        public void ChangeExtent(GISMapActions actions)
        {
            double newminx = bottomleft.x, newminy = bottomleft.y,
                newmaxx = upright.x, newmaxy = upright.y;
            switch (actions)
            {
                case GISMapActions.zoomin:  //地图放大
                    newminx = ((getMinX() + getMaxX()) - getWidth() / ZoomingFactor) / 2;
                    newminy = ((getMinY() + getMaxY()) - getHeight() / ZoomingFactor) / 2;
                    newmaxx = ((getMinX() + getMaxX()) + getWidth() / ZoomingFactor) / 2;
                    newmaxy = ((getMinY() + getMaxY()) + getHeight() / ZoomingFactor) / 2;
                    break;
                case GISMapActions.zoomout:  //地图缩小
                    newminx = ((getMinX() + getMaxX()) - getWidth() * ZoomingFactor) / 2;
                    newminy = ((getMinY() + getMaxY()) - getHeight() * ZoomingFactor) / 2;
                    newmaxx = ((getMinX() + getMaxX()) + getWidth() *ZoomingFactor) / 2;
                    newmaxy = ((getMinY() + getMaxY()) + getHeight()* ZoomingFactor) / 2;
                    break;
                case GISMapActions.moveup:  //向上移动，即地图范围下移
                    newminy = getMinY() - getHeight() * MovingFactor;
                    newmaxy = getMaxY() - getHeight() * MovingFactor;
                    break;
                case GISMapActions.movedown:  //向下移动，即地图范围上移
                    newminy = getMinY() + getHeight() * MovingFactor;
                    newmaxy = getMaxY() + getHeight() * MovingFactor;
                    break;
                case GISMapActions.moveleft:  //向左移动
                    newminx = getMinX() + getWidth() * MovingFactor;
                    newmaxx = getMaxX() + getWidth() * MovingFactor;
                    break;
                case GISMapActions.moveright:  //向右移动
                    newminx = getMinX() - getWidth() * MovingFactor;
                    newmaxx = getMaxX() - getWidth() * MovingFactor;
                    break;
            }
            upright.x = newmaxx;
            upright.y = newmaxy;
            bottomleft.x = newminx;
            bottomleft.y = newminy;
        }

        public void CopyFrom(GISExtent extent)//使用Extent替换当前值
        {
            upright.CopyFrom(extent.upright);
            bottomleft.CopyFrom(extent.bottomleft);
        }
    }



    public class GISView   //空间对象浏览类
    {
       GISExtent CurrentMapExtent;//记录显示的地图范围
        Rectangle MapWindowSize;  //记录绘图窗口的大小 
        double MapMinX, MapMinY;
        int WinW, WinH;
        double MapW, MapH;
        double ScaleX, ScaleY;
        public GISView(GISExtent _extent, Rectangle _rectangle)
        {
            UpdateMap(_extent, _rectangle);
        }

        /// <summary>
        /// 更新地图
        /// </summary>
        /// <param name="_extent"></param>
        /// <param name="_rectangle"></param>
        public void UpdateMap(GISExtent _extent, Rectangle _rectangle)
        {
            CurrentMapExtent = _extent;//当前地图范围
            MapWindowSize = _rectangle;
            MapMinX = CurrentMapExtent.getMinX();//地图最小X值
            MapMinY = CurrentMapExtent.getMinY();
            WinW = MapWindowSize.Width;//窗口宽度
            WinH = MapWindowSize.Height;//窗口高度
            MapW = CurrentMapExtent.getWidth();
            MapH = CurrentMapExtent.getHeight();
            ScaleX = MapW / WinW;//比例尺=图上距离/实际距离
            ScaleY = MapH / WinH;
        }//更新地图

        public void UpdateExtent(GISExtent extent)//更新当前地图范围
        {
            CurrentMapExtent.CopyFrom(extent);
            UpdateMap(CurrentMapExtent, MapWindowSize);
        }

        public Point ToScreenPoint(GISVertex onevertex)//地图转屏幕点
        {
            double ScreenX = (onevertex.x - MapMinX) / ScaleX;
            double ScreenY = WinH-(onevertex.y - MapMinY) / ScaleY;
            return new Point((int)ScreenX, (int)ScreenY);
        }

        public GISVertex ToMapVertex(Point point)//屏幕转地图点
        {
            double MapX = ScaleX*point.X + MapMinX;
            double MapY =ScaleY * (WinH-point.Y) + MapMinY;
            return new GISVertex(MapX, MapY);
        }

        public void ChangeView(GISMapActions actions)//改变显示范围
        {
            CurrentMapExtent.ChangeExtent(actions);
            UpdateMap(CurrentMapExtent, MapWindowSize);
        }
    }

    public enum GISMapActions  //地图的缩放与平移操作
    {
         zoomin,zoomout,
         moveup,movedown,moveleft,moveright
    }


}
